package facade

import (
	"context"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/jinzhu/copier"
	"google.golang.org/protobuf/types/known/emptypb"
	command_service "gotham-plan-manage/internal/app/command_service"
	query_service "gotham-plan-manage/internal/app/query_service"
	"gotham-plan-manage/internal/interfaces/assembler"
	"gotham-plan-manage/pkg/jwt_util"
	"gotham-plan-manage/proto/gotham-plan-manage-proto/plan"
)

/*
   @author:zhongyang
   @date:2023/5/31
   @description:计划-接口层
*/

type PlanServer struct {
	plan.UnimplementedPlanApiServer
	commandService *command_service.PlanManageCommandService
	queryService   *query_service.PlanManageQueryService
	planAssembler  assembler.PlanManageAssembler
	logger         *log.Helper
}

func NewPlanServer(commandService *command_service.PlanManageCommandService, queryService *query_service.PlanManageQueryService, logger log.Logger) *PlanServer {
	return &PlanServer{commandService: commandService, queryService: queryService, logger: log.NewHelper(logger)}
}

func (p *PlanServer) Create(ctx context.Context, request *plan.CreateRequest) (*emptypb.Empty, error) {
	createRequest := p.planAssembler.ToCommandFromCreateRequest(request)
	err := p.commandService.CreatePlan(ctx, createRequest)
	if err != nil {
		return nil, err
	}
	return &emptypb.Empty{}, nil
}

func (p *PlanServer) Delete(ctx context.Context, request *plan.DeleteRequest) (*emptypb.Empty, error) {
	deleteCommand := p.planAssembler.ToCommandFromDeleteRequest(request)
	err := p.commandService.DeletePlan(ctx, deleteCommand)
	if err != nil {
		return nil, err
	}
	return &emptypb.Empty{}, nil
}

func (p *PlanServer) Edit(ctx context.Context, request *plan.EditRequest) (*emptypb.Empty, error) {
	editCommand := p.planAssembler.ToCommandFromEditRequest(request)
	err := p.commandService.EditPlan(ctx, editCommand)
	if err != nil {
		return nil, err
	}
	return &emptypb.Empty{}, nil
}

func (p *PlanServer) GetOne(ctx context.Context, request *plan.PlanIdRequest) (*plan.GetOneResponse, error) {
	getPlanQuery := p.planAssembler.ToQueryFromGetPlanRequest(request)
	planRes, err := p.queryService.FindPlan(ctx, getPlanQuery)
	if err != nil {
		return nil, err
	}
	res := &plan.GetOneResponse{}
	_ = copier.Copy(&res, planRes)
	return res, nil
}

func (p *PlanServer) GetAll(ctx context.Context, empty *emptypb.Empty) (*plan.GetAllResponse, error) {
	allPlan, err := p.queryService.GetAllPlan(ctx, jwt_util.GetUserId(ctx))
	if err != nil {
		return nil, err
	}
	res := &plan.GetAllResponse{}
	_ = copier.Copy(&res.Plans, allPlan)
	return res, nil
}

func (p *PlanServer) GetPage(ctx context.Context, request *plan.GetPageRequest) (*plan.GetPageResponse, error) {
	listQuery := p.planAssembler.ToQueryFromGetPlanList(request)
	list, total, err := p.queryService.FindPlanMultiLevelList(ctx, listQuery)
	if err != nil {
		return nil, err
	}
	res := &plan.GetPageResponse{
		Total:    int32(total),
		Page:     request.Page,
		PageSize: request.PageSize,
	}
	_ = copier.Copy(&res.List, list)
	return res, nil
}

func (p *PlanServer) GenerateReport(ctx context.Context, request *plan.PlanIdRequest) (*plan.PlanReportResponse, error) {
	reportQuery := p.planAssembler.ToQueryFromGenerateReportRequest(request)
	report, err := p.queryService.GeneratePlanReport(ctx, reportQuery)
	if err != nil {
		return nil, err
	}
	res := &plan.PlanReportResponse{}
	_ = copier.Copy(&res, report)
	return res, nil
}

func (p *PlanServer) FindReport(ctx context.Context, request *plan.PlanIdRequest) (*plan.PlanReportResponse, error) {
	reportQuery := p.planAssembler.ToQueryFromFindPlanReport(request)
	report, err := p.queryService.FindPlanReport(ctx, reportQuery)
	if err != nil {
		return nil, err
	}
	res := &plan.PlanReportResponse{}
	_ = copier.Copy(&res, report)
	return res, nil
}

func (p *PlanServer) SubmitReport(ctx context.Context, request *plan.SubmitReportRequest) (*emptypb.Empty, error) {
	submitCommand := p.planAssembler.ToCommandFromSubmitPlanReport(request)
	err := p.commandService.SubmitPlanReport(ctx, submitCommand)
	if err != nil {
		return nil, err
	}
	return &emptypb.Empty{}, nil
}

func (p *PlanServer) EditTarget(ctx context.Context, request *plan.EditTargetRequest) (*emptypb.Empty, error) {
	editCommand := p.planAssembler.ToCommandFromEditTargetRequest(request)
	err := p.commandService.EditTarget(ctx, editCommand)
	if err != nil {
		return nil, err
	}
	return &emptypb.Empty{}, nil
}

func (p *PlanServer) GetDetail(ctx context.Context, request *plan.PlanIdRequest) (*plan.GetDetailResponse, error) {
	detailQuery := p.planAssembler.ToQueryFromGetPlanDetailRequest(request)
	detail, err := p.queryService.FindPlanDetail(ctx, detailQuery)
	if err != nil {
		return nil, err
	}
	res := &plan.GetDetailResponse{}
	_ = copier.Copy(&res, detail)
	return res, nil
}

func (p *PlanServer) CompletionRateAnalysis(ctx context.Context, request *plan.PlanIdRequest) (*plan.CompletionRateAnalysisResponse, error) {
	analysisQuery := p.planAssembler.ToQueryFromCompletionRateAnalysisRequest(request)
	analysis, err := p.queryService.CompletionRateAnalysis(ctx, analysisQuery)
	if err != nil {
		return nil, err
	}
	res := &plan.CompletionRateAnalysisResponse{}
	_ = copier.Copy(&res.Items, analysis)
	return res, nil
}

func (p *PlanServer) GetOngoingPlan(ctx context.Context, empty *empty.Empty) (*plan.GetOngoingPlanResponse, error) {
	resDTO, err := p.queryService.GetOngoingPlan(ctx)
	if err != nil {
		return nil, err
	}
	res := &plan.GetOngoingPlanResponse{}
	_ = copier.Copy(&res, resDTO)
	return res, nil
}

func (p *PlanServer) WeeklyDistributionAnalysis(ctx context.Context, req *plan.PlanIdRequest) (*plan.WeeklyDistributionAnalysisResponse, error) {
	query := p.planAssembler.ToQueryFromWeeklyDistributionAnalysisRequest(req)
	analysis, err := p.queryService.WeeklyDistributionAnalysis(ctx, query)
	if err != nil {
		return nil, err
	}
	res := &plan.WeeklyDistributionAnalysisResponse{}
	_ = copier.Copy(&res.Items, analysis)
	return res, nil
}

func (p *PlanServer) ReviewAnalysis(ctx context.Context, req *plan.ReviewAnalysisRequest) (*plan.ReviewAnalysisResponse, error) {
	query := p.planAssembler.ToQueryFromReviewAnalysisRequest(req)
	analysis, err := p.queryService.ReviewAnalysis(ctx, query)
	if err != nil {
		return nil, err
	}
	res := &plan.ReviewAnalysisResponse{}
	_ = copier.Copy(&res, analysis)
	return res, nil
}

func (p *PlanServer) SetExpectTaskTotal(ctx context.Context, req *plan.SetExpectTaskTotalRequest) (*empty.Empty, error) {
	command := p.planAssembler.ToCommandFromSetExpectTaskTotalRequest(req)
	err := p.commandService.SetExpectTaskTotal(ctx, command)
	if err != nil {
		return nil, err
	}
	return &emptypb.Empty{}, nil
}
